home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Essentials / C++ AppleLink Messages / CPlus.Dev$ 5⁄4⁄90 / 0120-Re copy vs op= & con-Apr90 < prev    next >
Encoding:
Text File  |  1990-05-04  |  5.5 KB  |  137 lines  |  [TEXT/GEOL]

  1. Item    7715524                         30-April-90        21:24PDT
  2.  
  3. From:   M.DANIEL                        Daniel Scientific, M Daniel,PRT
  4.  
  5. To:     CPLUS.APPLE$                    C++ Interest List--Apple Employees
  6.         CPLUS.DEV$                      C++ Interest List--Developers
  7.  
  8. Sub:    RE> copy vs op= & constr err
  9.  
  10. I have encountered both of these questions/problems.  My solution involves
  11. creating a more explicit philosophy of "object"  Then the answers come easy.
  12.  
  13. My explicit philosophy is:
  14.  
  15.     Objects are created from nothing.
  16.     Objects are destroyed to nothing.
  17.     In between creation and destruction, the object is either:
  18.     1) in a definite state, or
  19.     2) transforming from one definite state into another definite state.
  20.  
  21.  
  22.  
  23. Applied to C++:
  24.  
  25. A constructor transforms nothing into an object.  The memory allocation merely
  26. creates an empty "hole in space" where the object will exist on return from the
  27. constructor.  Before the constructor call, the values in this memory are
  28. meaningless.
  29.  
  30. Member functions transform the object from one state to another.  In between
  31. member function calls, the object is in a definite well-defined state.
  32.  
  33. A destructor transforms an object into nothing.  An empty "hole in space."  On
  34. return from it, the values of this memory are meaningless.
  35.  
  36.  
  37.  
  38. Copy constructors vs assignment operators.
  39.  
  40. A constructor has a right and an obligation to ignore the pre-existing values
  41. of the object.  The pre-existing values are part of nothing.  This is the
  42. nature of a constructor.
  43.  
  44. An assignment operator has a right and an obligation to consider the
  45. pre-existing values of the object.  The pre-existing values are part of an
  46. object.  This is the nature of an assignment operator.
  47.  
  48. So initialization and assignment are fundamentally different operations.
  49.  
  50. Practically, consider an object that contains a handle as a data member.
  51. If the constructor assumes its non-zero (junk) value is really a handle...
  52. (There is even a small probability, that it will actually be a valid handle).
  53. Or if an assignment operator assumes its valid value is really junk...
  54.  
  55.  
  56. Constructor HELL
  57.  
  58. When a constructor returns, its object must be in some definite state.
  59.  
  60. Then when a member function is called, it determines the state of the object,
  61. and uses it to decide what new state to transform the object into (as well as
  62. performing whatever other side effects are desired).
  63.  
  64. Practically, many object have only two states: OK and error.  And the state
  65. information can be implicit.  For example, a zero handle could mean error.
  66.  
  67.  
  68. The error handling/recovery thread
  69.  
  70. One idea I'm experimenting with is using the public member function
  71. "operator int();" to report the state of the object.  The basic idea is that to
  72. determine the state of an object, convert it to an integer.  Then to check the
  73. state, write:
  74.     if ( obj ) ...
  75.  
  76. I can also write more complex expressions:
  77.     if ( obj1 || ( obj2 && !obj3) ) ...
  78.  
  79. But, things could get a little sticky if an object had a lot of operators
  80. defined for it.  And even then, use an explicit int conversion:
  81.     cout << (int)obj << obj;
  82.  
  83. Using "operator int();" is, by definition, the only way to determine the state
  84. of an object.  Specifically, no other member function, public or private,
  85. returns state information.  This helps keep the error handling/recovery code
  86. thread from entangling the other code threads (ie. algorithm, interface,
  87. context-senstive help).  The threads will cross at a minimum of simple,
  88. obvious, well-behaved places.  If "operator int();" is inline, the generated
  89. code may even be better.
  90.  
  91. Note: Philosophically speaking, the "operator int();" member function
  92. transforms the object from state A into state A.  (ie it transforms the object,
  93. but the state does not change)
  94.  
  95. I define two more member functions in the error handling/recovery thread.
  96.  
  97. The first is the famous error() function.  What I have it do is examine the
  98. object, determine the error, set the object to indicate the error state, and
  99. place the object in a stable state.  This is the only function that transform
  100. the object into the error state.  I attempt to have it determine error by
  101. examine the current objects (transient) state, and refrain from passing
  102. parameters to it, because they clutter up the source files.
  103.  
  104. For example, an object may have several handles. If some are allocated when
  105. memory runs out, obj::error() would discover some zero handles, and release the
  106. rest of the memory, and set the state to reflect an error.
  107.  
  108. The last error thread function is obj::recover().  It is the one and only
  109. member function that can change an object from an error state to a non-error
  110. state (ie. recover from an error).  Don't forget to have it also handle objects
  111. that are not in an error state.
  112.  
  113. I also use the ideas Michael Vilot mentioned (ie. if the state is error, I do
  114. nothing).  Then the only place I check for object errors is at the beginning of
  115. certain member functions, and at strategic other locations.  Then, during an
  116. error condition, the rest of the code just calls and returns until it reaches
  117. one of these strategic locations.  If an error occurs during the execution of a
  118. member function, the obj::error() member function is called and the function
  119. returns.
  120.  
  121. (Looks a lot like poor man's exception handling, uh?)
  122.  
  123.  
  124.  
  125. Conclusion:
  126.  
  127. I have essentially applied Directed Acyclic Graph theory to object programming.
  128. DAGs are not particularily new to computer science, but I've yet to see object
  129. programming described this way.  Looks to me like an oppurtunity to create some
  130. new object-oriented CASE tools.
  131.  
  132.  
  133. Michael J. Daniel
  134. Daniel Scientific
  135. AppleLink:M.Daniel
  136.  
  137.